<?php

class Settings extends AbstractSingleton {

    private $hConfigs = array();

    /**
     * @return Settings
     */
    protected static function getInstance() { return parent::doGetInstance(get_class()); }

    public static function read($path, $name = null) { self::getInstance()->do_read($path, $name); }
    private function do_read($path, $name) {
        File::checkExistsAndReadable($path);
        if ($name === null) {
            $name = basename($path);
        }
        $this->hConfigs[$name] = new SettingsConfig(parse_ini_file($path, true));
    }

    /**
     * @return SettingsConfig
     */
    public static function config($name) { return self::getInstance()->do_config($name); }
    private function do_config($name) {

        $name .= '.ini';
        if (!isset($this->hConfigs[$name]))
            throw new NoConfigException("No config '$name'");

        return $this->hConfigs[$name];
    }
}

class SettingsConfig {

    private $hConfig;

    public function __construct(array $hConfig) {
        $this->hConfig = $hConfig;
    }

    public function getAll() {
        return $this->hConfig;
    }

    public function getSection($section) {
        $this->checkSectionExitst($section);
        return $this->hConfig[$section];
    }

    public function set($section, $param, $value) {
        $this->checkSectionExitst($section);
        $this->hConfig[$section][$param] = $value;
    }

    public function get($section, $param, $defaultValue = null) {

        $hSection = $this->getSection($section);

        if (isset($hSection[$param]))
            return $hSection[$param];

        if ($defaultValue === null)
            throw new NoConfigException("No section '$section'");

        return $defaultValue;
    }

    private function checkSectionExitst($section) {
        if (!isset($this->hConfig[$section]))
            throw new NoConfigException("No section '$section'");
    }
}

class NoConfigException extends Exception {}
?>